<?php

namespace App\Common\Machine;

use App\Common\CacheKey;
use App\Models\Machine;
use App\Services\EchoServer;
use App\Support\Time;
use Illuminate\Support\Facades\Cache;

/**
 * 玩家排队
 *
 * Class PlayerQueue
 * @package App\Common\Game
 */
class PlayerQueue
{
    /**
     * @var \App\Models\Machine
     */
    public $machine;
    
    /**
     * @var \App\Services\EchoServer
     */
    protected $echoServer;
    
    /**
     * @var string
     */
    protected $channel;
    
    /**
     * 玩家数组
     *
     * @var array
     */
    protected $players;
    
    public function __construct(Machine $machine)
    {
        $this->machine = $machine;
        
        $this->echoServer = app(EchoServer::class);
        
        $this->channel = "machines.{$this->machine->id}.player_queue";
    }
    
    /**
     * 排队的玩家
     *
     * @return array
     */
    public function players()
    {
        if (isset($this->players)) {
            return $this->players;
        }
        
        $this->players = $this->echoServer->getMembers($this->channel);
        
        return $this->players;
    }
    
    /**
     * 下一位玩家的用户id
     */
    public function nextUserId()
    {
        if (! $players = $this->players()) {
            return 0;
        }
        
        return $players[0]['user_id'];
    }
    
    /**
     * 当前队列长度
     *
     * @return int
     */
    public function length()
    {
        $players = $this->players();
        
        return count($players);
    }
    
    /**
     * 用于记录队列第一个用户的 cache key
     *
     * @return array
     */
    public function firstUserCacheKeys()
    {
        return [
            'id' => CacheKey::machinePlayerQueueFirstUserId($this->machine->id),
            'time' => CacheKey::machinePlayerQueueFirstUserTime($this->machine->id),
        ];
    }
    
    /**
     * 记录游戏回合通知信息，标记占用，后续以此检查是否超时占用
     *
     * @param int $userId
     */
    public function markOccupancy($userId)
    {
        $keys = $this->firstUserCacheKeys();
        
        // 上次记录是同一用户，则不更新
        if (Cache::get($keys['id'], 0) == $userId) {
            return;
        }
        
        Cache::put($keys['id'], $userId, Time::MINUTES_OF_HOUR);
        Cache::put($keys['time'], time(), Time::MINUTES_OF_HOUR);
    }
    
    /**
     * 开始游戏的权限是否被占用
     *
     * @param int $userId
     * @param int $timeout 占用的过期时间
     * @return bool
     */
    public function isOccupied($userId, $timeout)
    {
        $now = time();
        
        $keys = $this->firstUserCacheKeys();
        
        $lastUserId = Cache::get($keys['id'], 0);
        $lastTime = Cache::get($keys['time'], $now);
        
        if ($userId != $lastUserId || $lastTime + $timeout > $now) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 解除对游戏机开始权限的占用
     */
    public function releaseOccupancy()
    {
        $this->clearOccupancyMark();
        
        $players = $this->players();
        array_shift($players);
        
        $this->echoServer->setMembers($this->channel, $players);
    }
    
    /**
     * 清除“游戏机开始权限”的占用标记
     */
    public function clearOccupancyMark()
    {
        $keys = $this->firstUserCacheKeys();
        
        Cache::put($keys['id'], 0, Time::MINUTES_OF_HOUR);
        Cache::put($keys['time'], time(), Time::MINUTES_OF_HOUR);
    }
}
